package com.irdstudio.apicenter.gateway.web;

import java.io.IOException;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.irdstudio.apicenter.gateway.core.dm.AppBaseInfo;
import com.irdstudio.apicenter.gateway.core.jdbc.MaccsBaseDAO;
import com.irdstudio.apicenter.gateway.util.spring.BeanUtils;

/**
 * MACCS 移动应用通讯控制系统 本类作用：
 * 移动应用通讯控制系统启动入口及移动应用客户端统一接入类，有不同controller进行业务处理，结果有view展现。
 * 
 * @author Administrator
 * @modify by guangming.li
 * @date 2015-05-20 客户端启动过程安全校验：http://serverIP:port/mb.do
 *       业务功能调用:http://serverIP:port/*.do
 * 
 * 
 */
public class MaccsEntryServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private final static Logger logger = LoggerFactory.getLogger(MaccsEntryServlet.class);

	/* 用于存放通讯控制总线实例 */
	private static Map<String, MaccsControllerBus> ctrlBusFactory = new Hashtable<String, MaccsControllerBus>();

	/**
	 * 启动时初始化
	 */
	@Transactional("propagation=Propagation.NOT_SUPPORTED")
	public void init(ServletConfig config) throws ServletException {

		super.init(config);
		MaccsBaseDAO baseDAO = BeanUtils.getBean(MaccsBaseDAO.class);
		try {

			// 读取所有APP定义信息到列表
			List<AppBaseInfo> appList = baseDAO.findBeanList(AppBaseInfo.class);
			Assert.notEmpty(appList, "未找到APP定义信息!");

			// 循环每个APP的信息,为每个APP初始化一个通讯控制总线
			for (AppBaseInfo appBaseInfo : appList) {
				logger.info("开始初始化[ " + appBaseInfo.getAppName() + "]通讯总线...");
				// 读取通讯控制总线下的配置信息（交易、通道、报文要素）
				MaccsControllerBus ctrlBus = MaccsControllerBusUtil.loadBusConfigure(appBaseInfo.getAppId(), baseDAO);
				if (ctrlBus.isReady()) {
					ctrlBusFactory.put(appBaseInfo.getAppId(), ctrlBus);
					logger.info("初始化[" + appBaseInfo.getAppName() + "]通讯总线成功!");
				} else {
					logger.info("初始化[" + appBaseInfo.getAppName() + "]通讯总线失败!");
				}
			}

		} finally {
		}
	}

	/**
	 * 移动应用客户端请求接入处理主方法
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	protected void processRequest(HttpServletRequest request, HttpServletResponse response) {

		response.setContentType("text/html;charset=UTF-8");

		// 截获所有异常，在有异常的情况下默认返回JSON字符串给客户端
		try {

			// 直接获取请求的地址,去掉应用名称(即contextPath)
			String requestURI = request.getRequestURI();
			String contextPath = request.getContextPath();
			String realRequestURI = requestURI;
			if (requestURI.startsWith(contextPath))
				realRequestURI = requestURI.substring(contextPath.length() + 1);

			// 分解地址,地址第一段为APPID标识,后续为请求的交易名称及参数
			String appId = "", tradeId = "";
			int idx = realRequestURI.indexOf("/");
			if (idx != -1) {
				appId = realRequestURI.substring(0, idx);
				tradeId = realRequestURI.substring(idx + 1);
			} else {
				MaccsRenderUtil.renderNormalErrorJsonView(MaccsRenderUtil.INVALID_REQUEST, response);
			}
			logger.info("Request url=" + requestURI);

			// 根据APPID获取相应的通讯控制总线
			MaccsControllerBus maccsBus = ctrlBusFactory.get(appId);
			if (maccsBus == null) {
				// 初始化通讯控制总线后再进行处理
				if (!initializeControllerBus(appId)) {
					// 如果初始化不成功,直接告知应用端“初始化失败”
					MaccsRenderUtil.renderNormalErrorJsonView(MaccsRenderUtil.INITIALIZE_BUS_FAIURE, response);
				}
			}
			// 将请求交给相应的通讯控制总线处理
			maccsBus.execute(tradeId, request, response);

		} catch (Exception e) {
			logger.error("Process Error:", e);
			MaccsRenderUtil.renderCustomErrorJsonView("9999", e.getMessage(), response);
		}
	}

	/**
	 * 获取指定移动应用的总线
	 * 
	 * @param appId
	 * @return
	 */
	public MaccsControllerBus getMaccsControllerBus(String appId) {
		return ctrlBusFactory.get(appId);
	}

	/**
	 * 初始化指定APP的通讯控制总线
	 * 
	 * @param appId
	 */
	@Transactional("propagation=Propagation.NOT_SUPPORTED")
	private boolean initializeControllerBus(String appId) {
		boolean bInitialize = false;

		MaccsBaseDAO baseDAO = BeanUtils.getBean(MaccsBaseDAO.class);

		try {
			MaccsControllerBus ctrlBus = MaccsControllerBusUtil.loadBusConfigure(appId, baseDAO);
			if (ctrlBus.isReady()) {
				ctrlBusFactory.put(appId, ctrlBus);
				logger.info("初始化[" + appId + "]通讯总线成功!");
				bInitialize = true;
			} else {
				logger.info("初始化[" + appId + "]通讯总线失败!");
			}

		} catch (Exception e) {
			logger.error("初始化[" + appId + "]通讯总线失败!", e);
		} finally {
		}

		return bInitialize;

	}

	/**
	 * 移动应用客户端请求接入
	 */
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}

	/**
	 * 移动应用客户端请求接入
	 */
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}
}
